package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"math"
	"strconv"
	"time"
	"uniswap-web/model"
	"uniswap-web/util"
)

type Data map[string]interface{}

// 获取k线数据
func KLine(context *gin.Context) {

	target := context.DefaultQuery("target", "eth-usdc")
	interval := context.DefaultQuery("interval", "5m")
	start := context.Query("start")
	end := context.Query("end")
	//if start == "" {
	//	offset, _ := time.ParseDuration("-1h") // 默认偏移量
	//	start = time.Now().Add(offset).Format("2006-01-02 15:04:05")
	//}
	//if end == "" {
	//	end = time.Now().Format("2006-01-02 15:04:05")
	//}

	req := QueryKlineReq{
		target:   target,
		interval: interval,
		start:    start,
		end:      end,
	}
	fmt.Println(req)
	err := req.check()
	if err != nil {
		util.RetErrResp(context, -1, err.Error(), nil)
		return
	}
	bars := findEthUsdc(start, end)
	barBuff := handlebars(bars)
	fmt.Println(barBuff)
	data := Data{"bars": barBuff, "target": target, "start": start, "end": end, "interval": interval}
	util.RetSucResp(context, data)
	//context.JSON(200, barBuff)
}

// Bar k线数据类型
type Bar struct {
	Open   float64 `json:"open"`
	Close  float64 `json:"close"`
	High   float64 `json:"high"`
	Low    float64 `json:"low"`
	Volume float64 `json:"volume"`
	//Txs       []string `json:"txs"`
	BeginTime string `json:"begin_time"`
	StopTime  string `json:"stop_time"`
}

//字符串转float64
func string2float(s string) float64 {
	f, err := strconv.ParseFloat(s, 64)
	if err != nil {
		return 0
	}
	return f
}

// 处理bar数据
func handlebars(bars map[int][]model.EthUsdc) []Bar {
	barBuff := make([]Bar, 0, 10)
	for _, v := range bars {
		length := len(v)
		if length == 0 {
			//fmt.Println("emepty")
			bar := Bar{
				Open:   0.0,
				Close:  0.0,
				High:   0.0,
				Low:    0.0,
				Volume: 0.0,
				//Txs:    nil,
			}
			barBuff = append(barBuff, bar)
		} else {
			o := string2float(v[0].Price)
			c := string2float(v[length-1].Price)
			h := 0.0
			l := math.MaxFloat32
			vol := 0.0
			txs := make([]string, 0)

			for _, usdc := range v {
				p := string2float(usdc.Price)
				if p <= l {
					l = p
				}
				if p >= h {
					h = p
				}
				vol += string2float(usdc.Volume)
				txs = append(txs, usdc.TxHash)
			}

			bar := Bar{
				Open:   o,
				Close:  c,
				High:   h,
				Low:    l,
				Volume: vol,
				//Txs:    txs,
			}
			barBuff = append(barBuff, bar)
		}
	}
	return barBuff
}

// 数据库查询同步好的区块交易数据
func findEthUsdc(start, end string) map[int][]model.EthUsdc {
	var x time.Time
	var y time.Time
	if start == "" {
		offest, _ := time.ParseDuration("-1h")
		x = time.Now().Add(offest)
	} else {
		x, _ = time.Parse("2006-01-02 15:04:05", start)
	}

	if end == "" {
		//offset, _ := time.ParseDuration("-8h")
		y = time.Now()
	} else {
		y, _ = time.Parse("2006-01-02 15:04:05", end)
	}

	//fmt.Printf("左边界 %s 有边界%s \n", x.Format("2006-01-02 15:04:05"), y.Format("2006-01-02 15:04:05"))
	//fmt.Printf("左边界 %s 有边界%s \n", x.Unix(), y.Unix())
	p := int64(300)
	begin := int64(0)
	stop := int64(0)
	a := x.Unix()
	b := y.Unix()

	if a%p == 0 {
		begin = a
	} else {
		begin = (a / p) * p
	}
	if b%p == 0 {
		stop = b
	} else {
		stop = (b/p + 1) * p
	}
	fmt.Println(a, b)
	fmt.Println(begin, stop)

	//// 找到相关的数据集合
	tx := make([]model.EthUsdc, 0, 20)
	db.Table("eth_usdcs").Where("timestamp > ? and timestamp < ?", begin, stop).Find(&tx)
	//fmt.Println(tx)

	// 合并数据
	//bars := make(map[int][]model.EthUsdc)
	bars := make(map[int][]model.EthUsdc)

	for i := int64(0); i < (stop-begin)/p; i++ {
		indexBegin := begin + i*p
		indexStop := begin + (i+1)*p
		buff := make([]model.EthUsdc, 0, 10)
		for _, usdc := range tx {
			if usdc.Timestamp <= uint64(indexBegin) {
				continue
			}
			if usdc.Timestamp > uint64(indexStop) {
				break
			}
			buff = append(buff, usdc)
		}
		bars[int(i)] = buff
	}
	return bars

}

// QueryKlineReq 请求
type QueryKlineReq struct {
	target   string
	interval string
	start    string
	end      string
}

// 数据检测
func (req QueryKlineReq) check() error {
	if req.target != "eth-usdc" {
		return fmt.Errorf("target is not support:%s", req.target)
	}
	if req.interval != "5m" {
		return fmt.Errorf("interval is not support for the moment:%s", req.interval)
	}

	ts, err := time.Parse("2006-01-02 15:04:05", req.start)
	if err != nil && req.start != "" {
		return fmt.Errorf("start is not legal,like:2006-01-02 15:04:05 :%s", req.start)
	}
	te, err := time.Parse("2006-01-02 15:04:05", req.end)
	if err != nil && req.end != "" {
		return fmt.Errorf("end is not legal,:%s", req.end)
	}
	if ts.Unix() > te.Unix() {
		return fmt.Errorf("start %s can not bigger than end %s", req.start, req.end)
	}

	return nil
}
